from grafo import grafo

def calcular_rutas(grafo):
	""" calcula todas las rutas de la red """
	total = {}
	for v in grafo.get_vertices():
		print "calculando ruta para {0}".format(v)
		parcial = _calcular_rutas(grafo, v)
		total.update(parcial)
	return total



def _calcular_red(par):
	ip, mascara = par
	partes_mascara = map(int, mascara.split('.'))
	partes_ip = map(int, ip.split('.'))
	aux = []
	for i in xrange(4):
		aux.append(partes_mascara[i] & partes_ip[i])
	return ".".join(map(str, aux))
	


def _calcular_rutas(grafo, raiz):
	""" calcula todas las rutas de un vertice raiz """
	rutas  = {}
	for vi in grafo.get_vecinos(raiz):	
		_calcular_rutas_r(grafo, rutas, raiz, vi, raiz, vi, 0, [])
	return rutas

def _es_valida(raiz, origen, padre, v):
	""" verifica que se de la condicion de que la ruta sea valida, es decir, que no sea el padre, no sea el origen ni la raiz """
	return v != origen and v != padre and v != raiz

def _calcular_rutas_r(grafo, rutas, raiz, origen, padre, actual, p, redes):
	""" rutina recursiva que se encarga de rellenar el diccionario de rutas """
	rutas_validas = [ v for v in grafo.get_vecinos(actual) if _es_valida(raiz, origen, padre, v)]
	if not raiz in rutas:
		rutas[raiz] = []
	dato = (grafo.get_arista(padre, actual), origen, p)
	red = _calcular_red(dato[0])
	if red not in redes:
		redes.append(red)
		my_print("R5", raiz, dato)
		rutas[raiz].append(dato)
	for v in rutas_validas:
		if _calcular_red(grafo.get_arista(padre,actual)) != _calcular_red(grafo.get_arista(actual,v)):		
			_calcular_rutas_r(grafo, rutas, raiz, origen, actual, v, p + 1, redes)

def my_print(cond, vertice, dato):
	if cond == vertice:
		print "estoy agregando en {} la ruta {}".format(vertice, dato)


def armar_rutas(grafo, rutas):
	""" rutina que se encarga de exportar las rutas en distintos archivos con los comandos como para agregar a la configuracion de los routers """
	try:
		for v in grafo.get_vertices():
			print "exportando configuracion para {0}".format(v)
			with open(v, 'w') as fconf:
				if v not in rutas:
					continue
				for ruta in rutas[v]:
					if ruta[2] == 0:
						continue
					fconf.write("ip route {0} {1} {2} {3}\n".format(_calcular_red(ruta[0]), ruta[0][1], grafo.get_arista(v,ruta[1])[0], ruta[2]))
	except IOError:
		print "error de manejo de archivos"
	except KeyError:
		print "error de manejo de grafo con las claves"

def main():
	print "leyendo configuracion"
	graf = grafo("conf_grafo")
	print "calculando rutas"
	rutas = calcular_rutas(graf)
	print "exportando rutas"
	armar_rutas(graf, rutas)
	print "proceso finalizado"

main()
